/*jslint browser: true, devel: true, bitwise: true, white: true, plusplus: true, forin:true */
/*global $:true, define:true */

/**
 * @module Data
 */

define(function() {
"use strict";

/** Lista dwukierunkowa.
 * @class LinkedList
 * @constructor
 */
var 
	LinkedList = function() {
		this.head = undefined;
		this.tail = undefined;
		this.length = 0;
	}, 
	Node = function(data,prev,next) {
		this.data = data;
		this.prev = prev;
		this.next = next;
	}, 
	
	Iterator = function(node) {
		this.Current = node;
	};
	
LinkedList.prototype = {
	constructor: LinkedList,
	
	append: function(data) {
		var node = new Node(data);
	
		if (this.isEmpty()) {
			this.head = this.tail = node; 
		} else {
			if (this.Tail === this.head) {
				node.prev = this.head;
				this.head.next = node;
				this.tail = node;
			} else {
				this.tail.next = node;
				node.prev = this.tail;
				this.tail = node;
			}
		}
		
		++this.length;
		return node;
	},
	
	insertBefore: function(data, node) {
		var n = new Node(data,node.prev,node);
		if (node === this.head) {
			this.head = n;
		} else {
			node.prev.next = n;
		}
		
		node.prev = n;
		++this.length;
		return n;
	},
	
	insertAfter: function(data, node) {
		var n = new Node(data,node,node.next);
		if (node === this.tail) {
			this.tail = n;
		} else {
			node.next.prev = n;
		}
		
		node.next = n;
		++this.length;
		return n;
	},
	
	remove: function(node) {
		if (this.length === 1) {
			this.head = this.tail = undefined;
		} else {
			if (node === this.head) {
				this.head = node.next;
				this.head.prev = undefined;
			} else if (node === this.tail) {
				this.tail = node.prev;
				this.tail.next = undefined;
			} else {
				node.prev.next = node.next;
				node.next.prev = node.prev;
			}
		}
		--this.length;
	},
	
	iterator: function() {
		return new Iterator(this.head);
	},
	
	reverseIterator: function() {
		return new Iterator(this.tail);
	},
	
	isEmpty: function() {
		return !this.length;
	}
};

Iterator.prototype = {
	constructor: Iterator,
	next: function() {
		var data;
		if (this.hasNext()) {
			data = this.Current.data;
			this.Current = this.Current.next;
		}
		return data;
	},
	
	prev: function() {
		var data;
		if (this.hasPrev()) {
			data = this.Current.data;
			this.Current = this.Current.prev;
		}
		return data;
	},
	
	hasNext: function() {
		return Boolean(this.Current.next);
	},
	
	hasPrev: function() {
		return Boolean(this.Current.prev);
	}
};

return LinkedList;
});
